import * as fs from 'fs';
import * as path from 'path';
import * as os from 'os';

export type LogLevel = 'info' | 'warn' | 'error' | 'debug';

export class Logger {
    private logDir: string;
    private logFile: string;
    private level: LogLevel;
    private static instance: Logger;

    private constructor(level: LogLevel = 'info') {
        const home = os.homedir();
        this.logDir = path.join(home, '.dify-code-review', 'logs');
        if (!fs.existsSync(this.logDir)) {
            fs.mkdirSync(this.logDir, { recursive: true });
        }
        this.logFile = this.getLogFilePath();
        this.level = level;
    }

    public static getInstance(level: LogLevel = 'info'): Logger {
        if (!Logger.instance) {
            Logger.instance = new Logger(level);
        }
        return Logger.instance;
    }

    private getLogFilePath(): string {
        const date = new Date();
        const dateStr = date.toISOString().slice(0, 10); // yyyy-mm-dd
        return path.join(this.logDir, `dify-code-review-${dateStr}.log`);
    }

    private shouldLog(level: LogLevel): boolean {
        const levels: LogLevel[] = ['debug', 'info', 'warn', 'error'];
        return levels.indexOf(level) >= levels.indexOf(this.level);
    }

    private getBeijingTimeISOString(): string {
        const now = new Date();
        // 北京时间 = UTC时间 + 8小时
        const beijingTime = new Date(now.getTime() + 8 * 60 * 60 * 1000);
        return beijingTime.toISOString().replace('T', ' ').replace('Z', '');
    }

    private writeLog(level: LogLevel, message: string, error?: Error) {
        if (!this.shouldLog(level)) return;
        const now = this.getBeijingTimeISOString();
        let logMsg = `[${now} (UTC+8)] [${level.toUpperCase()}] ${message}`;
        if (error) {
            logMsg += `\n${error.stack || error.message}`;
        }
        logMsg += '\n';
        try {
            fs.appendFileSync(this.getLogFilePath(), logMsg, { encoding: 'utf8' });
        } catch (e) {
            // 降级到控制台
            // eslint-disable-next-line no-console
            console.error('日志写入失败:', e, logMsg);
        }
    }

    public info(message: string) {
        this.writeLog('info', message);
    }
    public warn(message: string) {
        this.writeLog('warn', message);
    }
    public error(message: string, error?: Error) {
        this.writeLog('error', message, error);
    }
    public debug(message: string) {
        this.writeLog('debug', message);
    }
} 